#include "../Core/NetMsgBusHelper.hpp"
#include "../Core/msgbus_interface.h"
#include "../Core/xparam.hpp"
#include "CmdParser.h"
#include "CmdFuncImpForReceiver.h"
#include "IMReceiver.h"
#include "../Biz/ConfigurationMgr.hpp"
#include "../Core/SimpleLogger.h"

#include <boost/noncopyable.hpp>
#include <string>
#include <stdio.h>

using namespace NetMsgBus;
using namespace wwcommon;
using namespace wwbiz;
using namespace core;

static LoggerCategory g_log("CmdIMReceiverMain");

class Cleaner
{
public:
    ~Cleaner()
    {
        MsgHandlerMgr::DropAllInstance();
        NetMsgBusDisConnect();
        DestroyMsgBus();
        threadpool::destroy_thread_pool();
        printf("CmdIMReceiverMain Quit!\n");
    }
};

void BuildAllCmds(CmdParser& cmdparser)
{
    //cmdparser.RegisterCmd("buildhelp", BuildHelpDetailFunc);
    cmdparser.RegisterCmd("help", HelpFunc);
    cmdparser.RegisterCmd("login", LoginFunc);
    cmdparser.RegisterCmd("relogin", ReLoginFunc);
    cmdparser.RegisterCmd("logout", LogoutFunc);
    cmdparser.RegisterCmd("sendmsg", SendMsgFunc);
    cmdparser.RegisterCmd("quit", QuitFunc);
    cmdparser.RegisterCmd("sendfile", SendFileFunc);
    cmdparser.RegisterCmd("exportbinmsgs", ExportBinMsgsFunc);
    cmdparser.RegisterCmd("recvfile", RecvFileFunc);
    cmdparser.RegisterCmd("rejectfile", RejectFileFunc);
    // show some useful information in current login session.
    // such as all contacts, all groups etcs.
    // cmdparser.RegisterCmd("info", InfoFunc);
}


int main(int argc, char* argv[])
{
    if(argc < 3)
    {
        printf("argument not enough, will exit.\n");
        return -1;
    }
    std::string wwmain_name("IMMainBiz");
    wwmain_name = argv[1];
    std::string receiver_name("IMReceiver");
    receiver_name = argv[2];

    // read global configuration
    bool ret = ConfigurationMgr::Instance().LoadConfig();
    if(!ret)
    {
        printf("read configuration error, CmdIMReceiverMain start failed.\n");
        return -1;
    }
    int server_port = 9000;
    int imreceiver_port;
    IMGet_CommonConfig("serverport", server_port);
    IMGet_CommonConfig("imreceiverport", imreceiver_port);

    Cleaner  cleaner_;

    threadpool::init_thread_pool();

    // init the logger.
    //
    int loglevel = lv_warn;
    IMGet_CommonConfig("loglevel", loglevel);
    SimpleLogger::Instance().Init(utility::GetModulePath() + "/CmdIMReceiverMain_log.log", (LogLevel)loglevel);

    InitMsgBus(0);
    int retry = 3;
    while(0 != NetMsgBusConnectServer("127.0.0.1",server_port))
    {
        if(retry-- < 0)
        {
            printf("connect msgbus server error.\n");
            return -1;
        }
        sleep(1);
    }
    RegisterReceiverHandlerPtr receiver_handler;
    MsgHandlerMgr::CreateInstance(receiver_handler);

    unsigned short result_port = (unsigned short)imreceiver_port;
    if( 0 != NetMsgBusRegReceiver(receiver_name, "", result_port))
    {
        printf("register receiver client error.\n");
        return -1;
    }

    // make sure register is success return
    if(!receiver_handler->WaitForRsp())
    {
        printf("reg receiver failed, quit the receiver.\n");
        return -1;
    }

    receiver_handler->RemoveAllHandlers();

    {
        boost::shared_ptr<IMReceiver> receiver(new IMReceiver());
        receiver->InitMsgHandler();
        receiver->SetWWMainUniqueFlag(wwmain_name);
        receiver->NotifyReadyToWWMain();
        std::cout << " CmdIMReceiverMain Start OK. Note: You can also use the QT UI for receiver. See Readme for Detail" << std::endl;
        std::cout << " type help for available command." << std::endl;

        CmdParser inputparser;
        BuildAllCmds(inputparser);

        while(receiver->IsRunning())
        {
            // ReadCmd
            int ret = inputparser.ReadCmd();
            if(!receiver->IsRunning())
            {
                //printf("receiver will quit since main process quit.\n");
                break;
            }
            if(ret == 0)
                break;
            else if(ret == -1)
                continue;

            // ExecuteCmd
            inputparser.ExecuteCmd();
        }

        receiver->NotifyQuitToWWMain();
        receiver->RemoveAllHandlers();
    }

}

